package com.gpj.sqlbuilder.utils;

import com.gpj.sqlbuilder.sysfun.SystemFunction;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.formula.functions.T;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;

/**
 * @className ReflectUtil
 * @description
 *   TODO
 * @author GPJ
 * @date 2023-05-22 19:31
 * @version 1.0
 **/
@Slf4j
public class ReflectUtil {
	private static final Map<Class, Class> ARRAY_CLASS_MAP = new HashMap();
	static {
		ARRAY_CLASS_MAP.put(String.class, String[].class);
	}
	/**
	 * 利用反射调用方法
	 * @param instance 如果传入Class对象,则表示调用静态方法
	 * @param name 方法名
	 * @param args 参数
	 */
	public static Object invoke(Object instance, String name, Object... args) {
		Class[] argClass = null;
		if(args != null && args.length > 0){
			argClass = new Class[args.length];
			for (int i = 0; i < args.length; i++) {
				argClass[i] = args[i].getClass();
			}
		}

		try {
			if(instance instanceof Class){
				Method method = SystemFunction.class.getMethod(name, argClass);
				return method.invoke(null, args);
			}else{
				Method method = instance.getClass().getDeclaredMethod(name, argClass);
				method.setAccessible(true);
				return method.invoke(instance, args);
			}
		} catch (Exception e) {
			log.error("内置函数调用错误:{}", e.getMessage());
			if(log.isDebugEnabled()){
				log.error(e.getMessage(), e);
			}
			return "";
		}
	}

	/**
	 * 通过Get方法获取属性值
	 * @param instance 对象
	 * @param fieldName 属性名
	 */
	public static Object getValueByMethod(Object instance, String fieldName){
		String methodName;
		try {
			Field field = instance.getClass().getDeclaredField(fieldName);
			String prefix = field.getType() == boolean.class || field.getType() == Boolean.class ? "is" : "get";
			methodName = prefix + StringUtils.capitalize(fieldName);
		} catch (NoSuchFieldException e) {
			methodName = fieldName;
		}
		try {
			return instance.getClass().getMethod(methodName).invoke(instance);
		} catch (Exception e) {
			return null;
		}
	}
}
